package hero_info

import (
	"go_server/game_server/api/service/bag"
	"go_server/game_server/dataconfig/config_manager"
	"go_server/game_server/event_manager"
	"go_server/game_server/event_manager/event_data/event_impl"
	"go_server/game_server/protocol/pb"
	"go_server/game_server/util"
	"go_server/game_server/world_manager"
	"go_server/zinx/ziface"
	"go_server/zinx/zlog"
)

func (s *Hero_info_service) S2C_UpStarHero(conn ziface.IConnection, roleid int64, msg *pb.UpStarHeroC2S) pb.ErrorCodeManager {
	hero := Hero_info_serviceObj.LoadByRoleId(roleid)
	if hero != nil {
		msgS2C, code := onUpStarHero(hero, msg.Heroserid, msg.Fragments, msg.Items)
		defer func() {
			if msgS2C != nil {
				zlog.Debugf("ProtocolManager_UpStarHero %v", msgS2C)
				defer func() {
					conn.SendBuffPBMsg(uint32(pb.ProtocolManager_UpStarHero), msgS2C)
				}()
			}
		}()
		return code
	}
	return pb.ErrorCodeManager_HERO_INFO_NOT_ROLEID
}

func onUpStarHero(hero *Cache_hero_info, heroserid int32, c2sfragments map[int32]int32, c2sitems map[int32]int32) (*pb.UpStarHeroS2C, pb.ErrorCodeManager) {
	if uphero, ok := hero.Heros[heroserid]; ok {
		if maxstar, code, ok := uphero.GetMax_UpStar(hero.RoleId); ok {
			if uphero.StarId < maxstar {
				if h1, ok1 := config_manager.GetStcTableHero_SheetHeroConfig(uphero.CfgId); ok1 {
					beforestar := uphero.StarId

					legitems := util.NewSet[int32]()
					upstarconsumes := uphero.GetUpgradeStarConsumes()
					legitems.AddValue(upstarconsumes.Items.Elements()) //升级道具从配置表来
					legitems.Add(h1.Unlockitemid)                      //升星碎片是专属的

					isAllOkItem := true //是否是合法的升星道具

					usefragments := make(map[int32]int32)
					useitems := make(map[int32]int32)

					for id, _ := range c2sitems {
						isAllOkItem = isAllOkItem && legitems.Contains(id)
						useitems[id] = 0
					}

					for id, _ := range c2sfragments {
						isAllOkItem = isAllOkItem && legitems.Contains(id)
						usefragments[id] = 0
					}

					if isAllOkItem {
						if star1, ok1 := config_manager.GetStcTableHero_SheetStarConfig(uphero.get_next_star()); ok1 {

							needfragmentconsume := star1.Consume1 //需要的英雄升星碎片数量
							if needfragmentconsume > 0 {
								for id, count := range c2sfragments {
									for i := 0; i < int(count); i++ {
										usefragments[id]++
										needfragmentconsume--
										if needfragmentconsume <= 0 {
											break
										}
									}
									if needfragmentconsume <= 0 {
										break
									}
								}
							}

							needitemconsume := star1.Consume2 //需要的英雄升星徽章(道具)数量
							if needitemconsume > 0 {
								for id, count := range c2sitems {
									for i := 0; i < int(count); i++ {
										useitems[id]++
										needitemconsume--
										if needitemconsume <= 0 {
											break
										}
									}
									if needitemconsume <= 0 {
										break
									}
								}
							}

							if needfragmentconsume <= 0 && needitemconsume <= 0 { //指定使用的道具足够
								totaluseitems := make(map[int32]int32)
								for id, count := range usefragments {
									if count > 0 {
										if _, ok := totaluseitems[id]; ok {
											totaluseitems[id] += count
										} else {
											totaluseitems[id] = count
										}
									}
								}
								for id, count := range useitems {
									if count > 0 {
										if _, ok := totaluseitems[id]; ok {
											totaluseitems[id] += count
										} else {
											totaluseitems[id] = count
										}
									}
								}
								isEnough := totaluseitems != nil
								isEnough = bag.CheckBatchItemEnough(hero.RoleId, totaluseitems)

								if isEnough {
									uphero.CalculateFight()

									//物品数量足够，可以进行升星操作
									uphero.StarId = uphero.get_next_star()

									msgS2C := &pb.UpStarHeroS2C{}
									msgS2C.Heros = make([]*pb.HeroCardData, 1)
									msgS2C.Heros[0] = uphero.ToPB_HeroCardData()
									go bag.SubItemBatch(hero.RoleId, totaluseitems)
									go event_manager.EventManagerObj.FireEventData(event_impl.NewUpStarHeroEvent(world_manager.WorldMgrObj.GetPlayerConn(hero.RoleId), uphero.SerId, beforestar, uphero.StarId))

									defer hero.SaveDB_HeroInfo_Heros()
									return msgS2C, pb.ErrorCodeManager_SUCCESS
								} else {
									return nil, pb.ErrorCodeManager_HERO_INFO_NOTENOUGH_HEROUPSTARITEM
								}

							} else {
								return nil, pb.ErrorCodeManager_HERO_INFO_NOTENOUGH_HEROUPSTARITEM
							}
						} else {
							return nil, pb.ErrorCodeManager_HERO_INFO_NOT_HEROUPSTARCFGID
						}
					} else {
						return nil, pb.ErrorCodeManager_HERO_INFO_ERRO_HEROUPSTARITEM
					}
				} else {
					return nil, pb.ErrorCodeManager_HERO_INFO_NOT_HEROCFGID
				}
			} else {
				return nil, pb.ErrorCodeManager_HERO_INFO_NOT_MAXHEROSTAR
			}
		} else {
			return nil, code
		}
	} else {
		return nil, pb.ErrorCodeManager_HERO_INFO_NOT_ROLEID
	}
}
